﻿using Sgr.Domain.Entities;
using Sgr.Exceptions;
using Sgr.Identity.Services;
using Sgr.UPMS.Domain.Roles;
using System;
using System.Collections.Generic;
using System.Net.Cache;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Sgr.UPMS.Domain.Users
{
    public class UserManage : IUserManage
    {
        private readonly IUserRepository _userRepository;

        public UserManage(IUserRepository userRepository)
        {
            _userRepository = userRepository;
        }

        public async Task<User> CreateNewAsync(string loginName, IPasswordHashService passwordHashService, string passWord, bool isAdmin, long orgId, CancellationToken cancellationToken = default)
        {
            Check.StringNotNullOrWhiteSpace(loginName, nameof(loginName));

            var ruleCheckResult = await ValidateLoginNameUniquenessAsync(loginName, null, cancellationToken);
            if (!ruleCheckResult.IsComply)
                throw DomainException.ValidationError(ruleCheckResult.Message);

            return new User(loginName, passwordHashService, passWord, isAdmin, orgId);
        }

        public async Task<DomainRuleCheckResult> ValidateLoginNameUniquenessAsync(string loginName,
            long? excludeId = null,
            CancellationToken cancellationToken = default)
        {
            Check.StringNotNullOrWhiteSpace(loginName, nameof(loginName));
            if (!await _userRepository.LoginNameIsUniqueAsync(loginName, excludeId, cancellationToken))
                return DomainRuleCheckResult.Fail($"账号名称 {loginName} 已注册");
            return DomainRuleCheckResult.Ok();
        }

        public async Task<DomainRuleCheckResult> ValidatePhoneNumberUniquenessAsync(string phoneNumber,
            long? excludeId = null,
            CancellationToken cancellationToken = default)
        {
            Check.StringNotNullOrWhiteSpace(phoneNumber, nameof(phoneNumber));
            if (!await _userRepository.PhoneNumberIsUniqueAsync(phoneNumber, excludeId, cancellationToken))
                return DomainRuleCheckResult.Fail("手机号码已注册");
            return DomainRuleCheckResult.Ok();
        }

        public async Task<DomainRuleCheckResult> ValidateEmailUniquenessAsync(string email,
            long? excludeId = null,
            CancellationToken cancellationToken = default)
        {
            Check.StringNotNullOrWhiteSpace(email, nameof(email));
            if (!await _userRepository.EmailIsUniqueAsync(email, excludeId, cancellationToken))
                return DomainRuleCheckResult.Fail("电子邮箱已注册");
            return DomainRuleCheckResult.Ok();
        }

        public async Task<DomainRuleCheckResult> ValidateWeChatOpenIdUniquenessAsync(string weChatOpenId,
            long? excludeId = null,
            CancellationToken cancellationToken = default)
        {
            Check.StringNotNullOrWhiteSpace(weChatOpenId, nameof(weChatOpenId));
            if (!await _userRepository.WeChatOpenIdIsUniqueAsync(weChatOpenId, excludeId, cancellationToken))
                return DomainRuleCheckResult.Fail("微信账号OpenId已绑定");
            return DomainRuleCheckResult.Ok();
        }

        public async Task<DomainRuleCheckResult> ValidateWeChatUnionIdUniquenessAsync(string weChatUnionId,
            long? excludeId = null,
            CancellationToken cancellationToken = default)
        {
            Check.StringNotNullOrWhiteSpace(weChatUnionId, nameof(weChatUnionId));
            if (!await _userRepository.WeChatUnionIdIsUniqueAsync(weChatUnionId, excludeId, cancellationToken))
                return DomainRuleCheckResult.Fail("微信账号UnionId已绑定");
            return DomainRuleCheckResult.Ok();
        }

        /// <summary>
        /// 检查角色是否被用户使用
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> HasUserUseRoleAsync(long roleId, CancellationToken cancellationToken = default)
        {
            return await _userRepository.HasUserUseRoleAsync(roleId, cancellationToken);
        }

        /// <summary>
        /// 检查用户是否可以删除
        /// </summary>
        /// <param name="user"></param>
        /// <param name="operatorUser"></param>
        /// <returns></returns>
        public DomainRuleCheckResult CheckBeforeDeletion(User user, User operatorUser)
        {
            Check.NotNull(user, nameof(user));
            Check.NotNull(operatorUser, nameof(operatorUser));

            //if (user.OrgId != operatorUser.OrgId && operatorUser.IsSuperAdmin)
            //    return DomainRuleCheckResult.Fail("只有组织下的管理员才能删除本组织下的账号");

            if (user.OrgId != operatorUser.OrgId)
                return DomainRuleCheckResult.Fail("管理员只能删除本组织下的账号");

            if (user.IsSuperAdmin)
                return DomainRuleCheckResult.Fail("超级管理员不允许删除");

            if (user.Id == operatorUser.Id)
                return DomainRuleCheckResult.Fail("不能删除自身账户");

            return DomainRuleCheckResult.Ok();
        }

        public async Task<bool> DeleteUserAsync(long userId, long operatorUserId, CancellationToken cancellationToken = default)
        {
            // 1. 获取待删除用户
            var user = await _userRepository.GetAsync(userId, cancellationToken);
            if (user == null)
                return false;

            // 2. 获取操作者
            var operatorUser = await _userRepository.GetAsync(operatorUserId, cancellationToken);
            if (operatorUser == null)
                return false;

            // 3. 检查是否可以删除
            var checkResult = CheckBeforeDeletion(user, operatorUser);
            if (!checkResult.IsComply)
                return false;

            // 4. 标记待删除
            user.MarkForDeletion();

            // 5. 调用仓储层执行实际的删除操作
            await _userRepository.DeleteAsync(user, cancellationToken);

            return true;
        }
    }
}